package cn.iocoder.yudao.module.pay.huifu;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ServerException;
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
import cn.iocoder.yudao.framework.pay.core.client.dto.huifu.UserBasicdataRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.huifu.UserBusiOpenRespDTO;
import cn.iocoder.yudao.framework.pay.core.client.dto.huifu.UserInfoReqDTO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.pay.api.huifu.dto.HuifuAddUserInfoReqDTO;
import cn.iocoder.yudao.module.pay.api.huifu.dto.HuifuUserInfoRespDTO;
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;

@Service
@Slf4j
public class HuifuUserInfoService {
    @Resource
    private PayChannelService channelService;
    @Resource
    private PayAppService appService;
    @Resource
    private MemberUserApi memberUserApi;

    /**
     * 汇付用户开户/修改用户信息
     * <p>
     * 处理逻辑：
     * 1. 校验应用和支付渠道是否有效，并获取对应支付客户端
     * 2. 查询当前用户在本地系统中是否已经存在汇付账号信息
     * - 如果已存在并且三要素（银行卡号、身份证号、预留手机号）一致，则直接返回
     * - 如果已存在但信息发生修改，则调用【用户业务入驻修改】接口更新信息
     * 3. 如果用户不存在汇付账号，则调用【用户基本信息开户】接口开户
     * 4. 开户成功后再调用【用户业务入驻】接口，完成银行卡绑定
     * 5. 将汇付ID和tokenNo更新到本地用户表中
     *
     * @param addUserInfoReqDTO 新增用户开户请求对象
     * @return HuifuUserInfoRespDTO 汇付开户结果，包含 huifuId、tokenNo
     */
    public HuifuUserInfoRespDTO createUserInfo(HuifuAddUserInfoReqDTO addUserInfoReqDTO) {
        // ==============================
        // 1. 校验支付应用和渠道有效性
        // ==============================
        PayAppDO payApp = appService.validPayApp(addUserInfoReqDTO.getAppKey());
        PayChannelDO channel = channelService.validPayChannel(payApp.getId(), addUserInfoReqDTO.getChannelCode());

        // 获取支付客户端（汇付专用）
        PayClient client = channelService.getPayClient(channel.getId());
        if (client == null) {
            log.error("[createUserInfo][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
            throw exception(CHANNEL_NOT_FOUND);
        }
        // ==============================
        // 2. 查询当前用户在本地系统的汇付信息
        // ==============================
        MemberUserRespDTO userRespDTO = memberUserApi.getUser(addUserInfoReqDTO.getUserId());
        if (userRespDTO == null) {
            throw new ServerException(500, "创建用户信息系统异常!");
        }
        String bankAccount = addUserInfoReqDTO.getBankAccount();
        String idNumber = addUserInfoReqDTO.getIdNumber();

//        MemberUserRespDTO userHuifuBankInfo = memberUserApi.getUserHuifuBankInfo(addUserInfoReqDTO.getUserId(), bankAccount, idNumber);
        // ==============================
        // 2.1 如果用户已经存在汇付ID
        // ==============================
        if (StrUtil.isNotEmpty(userRespDTO.getHuifuId())) {
            String existBankCard = userRespDTO.getBankCard();
            String existBankMobile = userRespDTO.getBankMobile();
            String existIdCard = userRespDTO.getIdCard();

            // 2.1.1 三要素未发生变化，直接返回
            if (ObjectUtil.equal(bankAccount, existBankCard)
                    && ObjectUtil.equal(idNumber, existIdCard)
                    && ObjectUtil.equal(addUserInfoReqDTO.getMobileNo(), existBankMobile)) {
                log.info("[汇付用户信息已存在--直接返回]");
                return new HuifuUserInfoRespDTO().setUserId(addUserInfoReqDTO.getUserId())
                        .setHuifuId(userRespDTO.getHuifuId()).setTokenNo(userRespDTO.getTokenNo());
            }
            // 2.1.2 三要素有变动，调用【用户业务入驻修改】接口
            log.info("[汇付用户信息已修改--开始修改]");
            UserInfoReqDTO userInfoReqDTO = BeanUtil.copyProperties(addUserInfoReqDTO, UserInfoReqDTO.class);
            userInfoReqDTO.setUserHuifuId(userRespDTO.getHuifuId());

            UserBusiOpenRespDTO userBusiOpenRespDTO = client.updateuserBusiOpen(userInfoReqDTO);
            if (!"00000000".equals(userBusiOpenRespDTO.getRespCode())) {
                throw exception(HUIFU_USER_INFO_BUSIOPEN_ERROR, userBusiOpenRespDTO.getRespDesc());
            }
            log.info("汇付用户业务入驻信息修改成功，userId={}，huifuId={}，tokenNo={}",
                    addUserInfoReqDTO.getUserId(), userRespDTO.getHuifuId(), userBusiOpenRespDTO.getTokenNo());

            // 更新信息到用户表里面
            memberUserApi.updateUserHuifuBankInfo(addUserInfoReqDTO.getUserId(), userInfoReqDTO.getMobileNo(),
                    userInfoReqDTO.getBankAccount(), userInfoReqDTO.getIdNumber(),
                    userRespDTO.getHuifuId(), userBusiOpenRespDTO.getTokenNo()
            );
            // 返回结果
            return new HuifuUserInfoRespDTO().setUserId(addUserInfoReqDTO.getUserId())
                    .setHuifuId(userRespDTO.getHuifuId()).setTokenNo(userBusiOpenRespDTO.getTokenNo());
        }

        // ==============================
        // 3. 如果用户不存在汇付账号，则开户
        // ==============================
        UserInfoReqDTO userInfoReqDTO = BeanUtil.copyProperties(addUserInfoReqDTO, UserInfoReqDTO.class);
        // 3.1 调用【用户基本信息开户】
        UserBasicdataRespDTO userBasicdataIndv = client.createUserBasicdataIndv(userInfoReqDTO);
        if (userBasicdataIndv == null || !"00000000".equals(userBasicdataIndv.getRespCode())) {
            throw exception(HUIFU_USER_INFO_CREATE_ERROR, userBasicdataIndv != null ? userBasicdataIndv.getRespDesc() : "未知错误");
        }
        String huifuId = userBasicdataIndv.getHuifuId();
        // 3.2 调用【用户业务入驻】
        userInfoReqDTO.setUserHuifuId(huifuId);
        UserBusiOpenRespDTO userBusiOpenRespDTO = client.userBusiOpen(userInfoReqDTO);
        if (!"00000000".equals(userBusiOpenRespDTO.getRespCode())) {
            throw exception(HUIFU_USER_INFO_BUSIOPEN_ERROR, userBusiOpenRespDTO.getRespDesc());
        }
        String tokenNo = userBusiOpenRespDTO.getTokenNo();
        log.info("汇付用户开户成功，userId={}，huifuId={}，tokenNo={}", addUserInfoReqDTO.getUserId(), huifuId, tokenNo);
        // 3.3 更新到用户表
        memberUserApi.updateUserHuifuBankInfo(addUserInfoReqDTO.getUserId(), userInfoReqDTO.getMobileNo(),
                userInfoReqDTO.getBankAccount(), userInfoReqDTO.getIdNumber(),
                huifuId, tokenNo
        );

        return new HuifuUserInfoRespDTO().setUserId(addUserInfoReqDTO.getUserId())
                .setHuifuId(huifuId).setTokenNo(tokenNo);
    }
}